import { Injectable } from "@angular/core";
import { FormControl, AbstractControl, ValidatorFn } from "@angular/forms";

const is: any = (window as any).is;
const REGEXES = {
    positiveInt: /^[1-9]\d*$/,
    filePath: /^([\/]{0,1}[A-Za-z0-9\_]+)+$/,
    ipv4: /^(?:(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(?:\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$/,
    ipv6: /^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i,
    url: /^(http[s]{0,1}|ftp):\/\/((([0-9]{1,3}\.){3}[0-9]{1,3})|([a-zA-Z0-9\.\-]+\.([a-zA-Z]{2,6})))(:\d+)?(\/[a-zA-Z0-9\-~!@#$%^&*+?:_\/=<>\.]*)?$/i, //必须带协议且无文件
    email: /^[a-zA-Z0-9]([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)*@([a-zA-Z0-9]*[-_]?[a-zA-Z0-9]+)+([\.][a-zA-Z0-9]+)*[\.][a-zA-Z]{2,3}([\.][a-zA-Z]{2})?$/,
    domain: /^(?=^.{3,128}$)(([^A-Z\s\/])+\.([^A-Z\s\/])+(\/\S*)*)$/,
    longitude:
        /^(\-|\+)?(((\d|[1-9]\d|1[0-7]\d|0{1,3})\.\d{0,6})|(\d|[1-9]\d|1[0-7]\d|0{1,3})|180\.0{0,6}|180)$/,
    latitude: /^(\-|\+)?([0-8]?\d{1}\.\d{0,6}|90\.0{0,6}|[0-8]?\d{1}|90)$/,
    MAC: /^[0-9a-fA-F]{2}-[0-9a-fA-F]{2}-[0-9a-fA-F]{2}-[0-9a-fA-F]{2}-[0-9a-fA-F]{2}-[0-9a-fA-F]{2}$/,
};

@Injectable({
    providedIn: "root",
})
export class ValidatorService {
    constructor() {}

    static specialcode(control: FormControl): { [prop: string]: {} } {
        if (!control.value) {
            return;
        }
        const special = /["%|=;<>:'\\]/;
        if (special.test(control.value)) {
            return { specialcode: "\"%|=;<>:'\\" };
        }
    }
    // 特殊字符 -- #^@/>
    static specialcodeConfig(control: FormControl): { [prop: string]: {} } {
        if (!control.value) {
            return;
        }
        const special = /[#^@/>]/;
        if (special.test(control.value)) {
            return { specialcode: "#^@/>" };
        }
    }

    // 特殊字符校验并集
    static specialcodeUnion(control: FormControl): { [prop: string]: {} } {
        if (!control.value) {
            return;
        }
        const special = /[%"|=;<>:'\\#^@/]/;
        if (special.test(control.value)) {
            return { specialcode: "%\"|=;<>:'\\#^@/" };
        }
    }

    // 特殊字符校验并集
    static nullinfo(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }

        // 允许的特殊值
        const specialValues = ["无", "未知"];

        // 如果是特殊值则直接通过
        if (specialValues.includes(control.value.trim())) {
            return;
        }

        // // 否则使用原有的ip验证逻辑
        // return ValidatorService.ip(control);
    }

    // 校验手机号
    static phonenumber(control: FormControl): { [prop: string]: {} } {
        if (!control.value) {
            return;
        }
        const reg =
            /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/;
        if (!reg.test(control.value)) {
            return { phonenumber: "请输入合法手机号" };
        }
    }

    // 数据源端口
    static port(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (
            !(
                REGEXES.positiveInt.test(control.value) &&
                Number(control.value) > 0 &&
                Number(control.value) <= 65535
            )
        ) {
            return { port: true };
        }
    }

    // 校验南向管理（A接口）端口
    static aport(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (
            !(
                REGEXES.positiveInt.test(control.value) &&
                Number(control.value) > 0 &&
                Number(control.value) < 65535
            )
        ) {
            return { aport: true };
        }
    }

    // 阈值校验---(0,100)的数字(小数最多为小数点后两位)校验
    static thresholdisRange(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        let ArrMen;
        if (control && control.value) {
            ArrMen = control.value.toString().split("."); // 截取字符串
            if (ArrMen.length === 2) {
                if (ArrMen[1].length > 2) {
                    return { thresholdisRange: true };
                }
            }
        }
        if (!(Number(control.value) > 0 && Number(control.value) < 100)) {
            return { thresholdisRange: true };
        }
    }

    static trimLength(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (control.value.trim().length == 0) {
            return { trimLength: true };
        }
    }

    // 标准名称1：只能包含英文字母、数字和下划线（以字母开头）
    static standardName1(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        const reg = /^[a-zA-Z][a-zA-Z0-9_]*$/;
        if (!reg.test(control.value)) {
            return { standardName1: true };
        }
    }

    // 正整数
    static positiveInt(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (!REGEXES.positiveInt.test(control.value)) {
            return { positiveInt: true };
        }
    }

    // url校验
    static url(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (!REGEXES.url.test(control.value)) {
            return { url: true };
        }
    }

    // MAC校验
    static mac(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (!REGEXES.MAC.test(control.value)) {
            return { mac: true };
        }
    }

    // 单个格式IPV4、IPV6校验
    static ip(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (ValidatorService.ipv4(control) && ValidatorService.ipv6(control)) {
            return { ip: true };
        }
    }

    // 单个格式及网段格式IPV4、IPV6校验
    static ipSegment(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (
            ValidatorService.ipv4Segment(control) &&
            ValidatorService.ipv6Segment(control)
        ) {
            return { ipSegment: true };
        }
    }

    //单个格式及网段格式IPV4、IPV6校验或者域名
    static ipAndDomain(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (
            ValidatorService.ipSegment(control) &&
            !REGEXES.domain.test(control.value)
        ) {
            return { ipAndDomain: true };
        }
    }

    // 单个格式IPV4校验
    static ipv4(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (!REGEXES.ipv4.test(control.value)) {
            return { ipv4: true };
        }
    }

    // 单个格式及网段格式IPV4校验
    static ipv4Segment(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (
            !(
                REGEXES.ipv4.test(control.value) ||
                ValidatorService.isIpv4Segment(control.value)
            )
        ) {
            return { ipv4Segment: true };
        }
    }

    // 单个格式IPV6校验
    static ipv6(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (!REGEXES.ipv6.test(control.value)) {
            return { ipv6: true };
        }
    }

    // 单个格式及网段格式IPV6校验
    static ipv6Segment(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (
            !(
                REGEXES.ipv6.test(control.value) ||
                ValidatorService.isIpv6Segment(control.value)
            )
        ) {
            return { ipv6Segment: true };
        }
    }

    // 是否为网段格式IPV4
    static isIpv4Segment(value: string) {
        const arr = value.split("/");
        if (
            arr.length === 2 &&
            REGEXES.ipv4.test(arr[0]) &&
            Number(arr[1]) > 0 &&
            Number(arr[1]) <= 32
        ) {
            return true;
        } else {
            return false;
        }
    }

    // 是否为网段格式IPV6
    static isIpv6Segment(value: string) {
        const arr = value.split("/");
        if (
            arr.length === 2 &&
            REGEXES.ipv6.test(arr[0]) &&
            Number(arr[1]) > 0 &&
            Number(arr[1]) <= 64
        ) {
            return true;
        } else {
            return false;
        }
    }

    // 校验密码长度限制8-32
    static passwordLengthLimit(control: FormControl): {
        [prop: string]: boolean;
    } {
        if (!control.value) {
            return;
        }
        if (
            control.value.trim().length < 8 ||
            control.value.trim().length > 32
        ) {
            return { minLengthPass: true };
        }
    }

    // 密码必须包含数字和字母
    static checkPassWord(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        const reg = new RegExp(/^(?![^a-zA-Z]+$)(?!\D+$)/);
        if (!reg.test(control.value)) {
            return { checkPassWord: true };
        }
    }

    // 文件系统类型数据源的文件路径校验
    static filePath(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (!REGEXES.filePath.test(control.value)) {
            return { filePath: true };
        }
    }

    /**
     * 某范围内非负整数校验
     * 若range = [1, 10]，表示范围为大于等于1小于等于10的整数
     */
    static IntRange(range: number[]): ValidatorFn {
        return (control: AbstractControl): { [prop: string]: number[] } => {
            if (!control.value) {
                return;
            }
            const reg = /^(0|([1-9]\d*))$/;
            const fromValue = range[0];
            const toValue = range[1];
            if (
                !(
                    reg.test(control.value) &&
                    Number(control.value) >= fromValue &&
                    Number(control.value) <= toValue
                )
            ) {
                return { IntRange: range };
            }
        };
    }

    /**
     * 邮箱校验
     * seperator为邮箱分隔符，count为邮箱个数限制
     */
    static emails(seperator: string, count: number): ValidatorFn {
        return (control: AbstractControl): { [prop: string]: string } => {
            if (!control.value) {
                return;
            }
            const emailList = control.value.split(seperator);
            if (emailList.length > count) {
                return { emails: `个数不能超过${count}个` };
            }
            for (let i = 0; i < emailList.length; i++) {
                if (!REGEXES.email.test(emailList[i])) {
                    return { emails: "格式有误" };
                }
            }
        };
    }

    static email(seperator: string, count: number): ValidatorFn {
        return (control: AbstractControl): { [prop: string]: string } => {
            if (!control.value) {
                return;
            }
            if (!REGEXES.email.test(control.value)) {
                return { emails: "格式有误" };
            }
        };
    }

    /**
     * json校验
     */
    static json(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        if (!ValidatorService.strIsJson(control.value)) {
            return { json: true };
        }
    }

    /**
     * 字符串是否是json
     */
    static strIsJson(str) {
        try {
            const obj = JSON.parse(str);
            if (is.json(obj)) {
                return true;
            } else {
                return false;
            }
        } catch (e) {
            return false;
        }
    }

    specialCode(value: string) {
        if (!value) {
            return {
                specialcode: "\"%|=;<>:'\\",
                result: false,
            };
        }
        const special = /["%|=;<>:'\\]/;
        if (special.test(value.trim())) {
            return {
                specialcode: "\"%|=;<>:'\\",
                result: true,
            };
        } else {
            return {
                specialcode: "\"%|=;<>:'\\",
                result: false,
            };
        }
    }

    // 数值范围
    isRange(value: any) {
        const regx = /^(0|([1-9]\d*))$/;
        const from = value.from;
        const to = value.to;
        const fromNum = from - 0;
        const toNum = to - 0;

        if (from === "" && to !== "") {
            if (!regx.test(to) || to <= 0) return false;
        } else if (from !== "" && to === "") {
            if (!regx.test(from)) return false;
        } else if (from !== "" && to !== "") {
            if (
                !regx.test(from) ||
                !regx.test(to) ||
                to === 0 ||
                fromNum >= toNum
            )
                return false;
        }

        return true;
    }

    //判断多个IPv6范围是否合法
    static isIpv6Ranges(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        let value = control.value.replace(/(\s)+|,|;|\n/g, ",");
        let ipArr = value.split(",");
        let flag: boolean = false;
        for (let i = 0; i < ipArr.length; i++) {
            if (!REGEXES.ipv6.test(ipArr[i])) {
                flag = true;
                break;
            }
        }
        if (flag) {
            return { isIpv6Ranges: true };
        }
    }

    /**校验多个 url 网址 */
    // url校验
    static multurl(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        let allValue: string[] = control.value
            .trim()
            .replace(/(\s)+|,|;|\n/g, " ")
            .split(/\s+/);
        for (let i = 0; i < allValue.length; i++) {
            if (!REGEXES.url.test(allValue[i])) {
                return { multurl: true };
            }
        }
        return null;
    }

    /**校验多个 domain 网址 */
    // domain校验
    static multdomain(control: FormControl): { [prop: string]: boolean } {
        if (!control.value) {
            return;
        }
        let allValue: string[] = control.value
            .trim()
            .replace(/(\s)+|,|;|\n/g, " ")
            .split(/\s+/);
        for (let i = 0; i < allValue.length; i++) {
            if (!REGEXES.domain.test(allValue[i])) {
                return { multdomain: true };
            }
        }
        return null;
    }

    // 经度校验
    static longitude(value): boolean {
        if (!value) {
            return;
        }
        return REGEXES.longitude.test(value);
    } // 纬度校验
    static latitude(value): boolean {
        if (!value) {
            return;
        }
        return REGEXES.latitude.test(value);
    }
}
